package com.manager.user.module.controller;

import com.manager.commons.Constant;
import com.manager.commons.utils.DateUtil;
import com.manager.core.module.manager.service.MainService;
import com.manager.user.module.entity.GenFiles;
import com.manager.user.module.entity.PlatformParameter;
import com.manager.user.module.entity.view.TreeNode;
import com.manager.user.module.service.FileDownloadService;
import com.manager.user.utils.MediaInfoUtils;
import com.manager.user.web.controller.AdminController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Controller
public class FileDownloadController extends AdminController<GenFiles> {

    @Autowired
    private MainService mainService;

    @Autowired
    private FileDownloadService _service;

    @GetMapping("/downloadFile")
    public void downloadFiles() throws IOException {
        Integer isDown = mainService.querDownPermission(getParams());
        if (isDown != null && isDown == 1) {
            try {
                String ids = getKeyParam("ids");
                String[] idArray = ids.split(",");
                List<String> intList = Arrays.asList(idArray);
                if (!intList.isEmpty()) {
                    PlatformParameter parameter = _service.getBaseParameter("UPLOAD_PATH");
                    // 文件存储的根目录，用于安全限制
                    String baseFileDir = parameter.getValue_vc() + parameter.getDescription() + MediaInfoUtils.ROOT_PATH;
                    GenFiles genFiles = _service.findPid(intList.get(0));
                    List<TreeNode> list = _service.getTreeNode(intList, genFiles.getId());
                    if (!list.isEmpty()) {
                        if (list.size() > 1) {
                            downloadMultipleFilesAsZip(list, baseFileDir);
                        } else {
                            downloadSingleFile(list.get(0), baseFileDir);
                        }
                    }
                }
            } catch (Exception e) {
                responseMsg("下载失败失败，请稍后在试！");
            }
        } else {
            responseMsg("对不起，您没有下载该文件的权限");
        }

    }

    private void responseMsg(String msg) throws IOException {
        // 无权限时返回提示信息
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.write("<script>alert('" + msg + "');history.back();</script>");
        out.flush();
        out.close();
    }

    /**
     * 直接下载单个文件
     */
    private void downloadSingleFile(TreeNode fileNode, String baseFileDir) throws IOException {
        File file = new File(baseFileDir + fileNode.getFilePath() + "/" + fileNode.getName());
        if (!file.exists() || !file.isFile() || !file.canRead()) {
            response.sendError(HttpStatus.NOT_FOUND.value(), "文件不存在或无法读取");
            return;
        }
        // 设置响应头
        response.setContentType(getContentType(file.getName()));
        String fileName = URLEncoder.encode(fileNode.getName(), StandardCharsets.UTF_8.name());
        response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
        response.setContentLengthLong(file.length());

        // 写入文件内容到响应流
        try (FileInputStream fis = new FileInputStream(file);
             BufferedInputStream bis = new BufferedInputStream(fis);
             OutputStream os = response.getOutputStream()) {

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = bis.read(buffer)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.flush();
        }
    }

    /**
     * 将多个文件打包成ZIP下载
     */
    private void downloadMultipleFilesAsZip(List<TreeNode> list, String baseFileDir) throws IOException {
        // 设置响应头
        response.setContentType("application/zip");
        String zipFileName = "资源文件下载-" + DateUtil.currentDate(DateUtil.DATE_FORMAR_STRING_yyyyMMddHHmm) + System.currentTimeMillis() + ".zip";
        String encodedFileName = URLEncoder.encode(zipFileName, StandardCharsets.UTF_8.name());
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION,
                "attachment; filename*=UTF-8''" + encodedFileName);

        // 3. 打包并写入响应流
        try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
            // 递归处理目录树节点
            for (TreeNode node : list) {
                processNode(baseFileDir, node, "", zipOut);
            }
            zipOut.finish();
        }
    }

    /**
     * 递归处理目录树节点，添加到ZIP文件
     */
    private void processNode(String baseFileDir, TreeNode node, String parentPath, ZipOutputStream zipOut) throws IOException {
        // 构建当前节点在ZIP中的路径
        String currentPath = parentPath + node.getName();

        if (node.getType().equals(Constant.FileType.FOLDER.getEcode())) {
            // 目录节点，路径以/结尾
            currentPath += "/";
            ZipEntry dirEntry = new ZipEntry(currentPath);
            zipOut.putNextEntry(dirEntry);
            zipOut.closeEntry();

            // 处理子节点
            for (TreeNode child : node.getChildren()) {
                processNode(baseFileDir, child, currentPath, zipOut);
            }
        } else {
            // 文件节点，添加文件内容
            File file = new File(baseFileDir + node.getFilePath() + "/" + node.getName());
            if (file.exists() && file.isFile() && file.canRead()) {
                ZipEntry fileEntry = new ZipEntry(currentPath);
                zipOut.putNextEntry(fileEntry);

                // 读取文件内容并写入ZIP
                try (FileInputStream fis = new FileInputStream(file)) {
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = fis.read(buffer)) != -1) {
                        zipOut.write(buffer, 0, bytesRead);
                    }
                }

                zipOut.closeEntry();
            }
        }
    }


    /**
     * 根据文件名获取内容类型
     */
    private String getContentType(String fileName) {
        // 简单的内容类型判断，实际应用中可以使用更完善的判断方式
        if (fileName.endsWith(".txt")) return "text/plain";
        if (fileName.endsWith(".pdf")) return "application/pdf";
        if (fileName.endsWith(".doc") || fileName.endsWith(".docx")) return "application/msword";
        if (fileName.endsWith(".xls") || fileName.endsWith(".xlsx")) return "application/vnd.ms-excel";
        if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) return "image/jpeg";
        if (fileName.endsWith(".png")) return "image/png";
        if (fileName.endsWith(".zip")) return "application/zip";
        return "application/octet-stream"; // 默认二进制流
    }

    @Override
    public GenFiles getModel() {
        return new GenFiles();
    }
}
